*-----------------------------------------------*
* Title: Replication Code for Jeannet, A.-M. and Dražanová, L. 2023. Blame it on my youth: the origins of attitudes towards immigration. Acta Politica. doi: 10.1057/s41269-023-00314-6   *
* Author: Lenka Dražanová                            *
* Date: 17/10/2023                                   *
* Description: This .do file provides all the necessary steps to replicate the analysis in the article  *
*-----------------------------------------------*

*use the European Social Survey's integrated file for 10 waves (2002-2020) "ESS10 - integrated file" 10.21338/ess10e03_1 available at https://ess-search.nsd.no/en/study/172ac431-2a06-41df-9dab-c1fd8f3877e7

local datafile "data/ESS1-10.dta"
use `datafile', clear

*install needed programs and schemes
set scheme plottig
ssc install oesch


** Section 1: Data Preparation
**COUNTRY SUBSAMPLE
***keeping only countries needed for the analysis: Austria, Belgium, Denmark, Finland, Germany, Ireland, Iceland, Italy, Netherlands, Norway, United Kingdom, Sweden, Switzerland
keep if cntry == "AT" | cntry == "BE" | cntry == "CH" | cntry == "DE" | cntry == "DK" | cntry == "FI" | cntry == "GB" | cntry == "IE" | cntry == "IS" | cntry == "IT" | cntry == "NL" | cntry == "NO" | cntry == "SE"
encode cntry, gen (country)
*changing the number 11 to number 14 because it created problems for the concatenation with cohort numbers otherwise
recode country 11=14
label define country1 1 "AT" 2 "BE" 3 "CH" 4 "DE" 5 "DK" 6 "FI" 7 "GB" 8 "IE" 9 "IS" 10 "IT" 12 "N0" 13 "SE" 14 "NL"
label values country country1

*separating the two Germanies
recode country 4=40 if intewde==1
label define country 40 "DE-E", modify
drop if country==40

*DEPENDENT VARIABLE (Gays and lesbians free to live life as they wish)
***creating an index variable
gen imgall=imbgeco+imueclt+imwbcnt

alpha imbgeco imueclt imwbcnt, item
omegacoef imbgeco imueclt imwbcnt

*INDIVIDUAL LEVEL INDEPENDENT VARIABLES
**AGE AND COHORT VARIABLES
***creating variable allage
gen allage = .m
replace allage=agea
***making sure there are enough observations for all ages
drop if allage<18
drop if allage>85 & allage<.
gen agesq=allage*allage

*Creating cohorts
generate cohort=.m
replace cohort=1 if yrbrn<1926
replace cohort=2 if yrbrn>=1926 & yrbrn<=1930
replace cohort=3 if yrbrn>=1931 & yrbrn<=1935
replace cohort=4 if yrbrn>=1936 & yrbrn<=1940
replace cohort=5 if yrbrn>=1941 & yrbrn<=1945
replace cohort=6 if yrbrn>=1946 & yrbrn<=1950
replace cohort=7 if yrbrn>=1951 & yrbrn<=1955
replace cohort=8 if yrbrn>=1956 & yrbrn<=1960
replace cohort=9 if yrbrn>=1961 & yrbrn<=1965
replace cohort=10 if yrbrn>=1966 & yrbrn<=1970
replace cohort=11 if yrbrn>=1971 & yrbrn<=1975
replace cohort=12 if yrbrn>=1976 & yrbrn<=1980
replace cohort=13 if yrbrn>=1981 & yrbrn<=1985
replace cohort=14 if yrbrn>=1986 & yrbrn<=1990
replace cohort=15 if yrbrn>=1991 & yrbrn<=1995
replace cohort=16 if yrbrn>=1996 & yrbrn<=2000
replace cohort=17 if yrbrn>=2001 & yrbrn<=.

label define cohort 1 "<1926 prewar" 2 " 26-30 post-war" 3 "31-35" 4 "36-40" ///
5 "41-45" 6 "46-50" 7 "51-55" 8 "56-60" 9 "61-65" 10 "66-70" 11 "71-75" 12 "76-80" ///
13 "81-85" 14 "86-90" 15 "91-95" 16 "96-00" 17 ">2001"
label variable cohort cohort

egen miss = rowmiss (cohort)
drop if miss==1
drop miss

*some cohorts have to be excluded from the analysis because they are not enough observations per period
drop if cohort==1
drop if cohort==2
drop if cohort==17


*EDUCATION
generate edu=.m
replace edu=eisced
recode  edu 55=.
replace edu = 1 if eisced== 0 & edulvla == 1 
replace edu = 2 if eisced== 0 & edulvla == 2 
replace edu = 3 if eisced== 0 & edulvla == 3 
replace edu = 5 if eisced== 0 & edulvla == 4 
replace edu = 6 if eisced== 0 & edulvla == 5 
recode edu 0=.
*creating education dummies
recode edu 1=1 .=. *=0, gen(llsec)
recode edu 2=1 .=. *=0, gen(lsec)
recode edu 3=1 4=1 .=. *=0, gen(usec)
recode edu 5=1 .=. *=0, gen(subdeg)
recode edu 6=1 7=1 .=. *=0, gen(uni)

*GENDER
recode gndr 1=0 2=1, gen(female)
*URBAN
recode domicil 1=1 2=1 .=. *=0, gen(urban)
*ECONOMIC SATISFACTION/INCOME DIFFICULTIES
recode hincfel 1=0 2=0 3=1 4=1, gen(incdiff)

*MINORITY
*1. Variable "borncntry" is a recoded version of the original "brncntr" variable in the ESS database:
gen borncntry = 0 if brncntr == 2
replace borncntry = 1 if brncntr == 1
*Where individuals not born in the country are assigned a "0", and individuals born in the country are assigned a "1".
*2. Variable "bornfather" is a recoded version of the original "facntr" variable in the ESS database:
gen bornfather = 0 if facntr == 2
replace bornfather = 1 if facntr == 1
*Where individuals where father was not born in the country are assigned a "0", and individuals where father was born in the country are assigned a "1".
*3. Variable "bornmother" is a recoded version of the original "mocntr" variable in the ESS database:
gen bornmother = 0 if mocntr == 2
replace bornmother = 1 if mocntr == 1
*Where individuals where mother was not born in the country are assigned a "0", and individuals where mother was born in the country are assigned a "1".
*Variable indicating that both parents were born in country
gen parentsborn1=.
replace parentsborn1 = 1 if bornfather == 1 & bornmother == 1
replace parentsborn1 = 0 if bornfather == 0 & bornmother == 0 
replace parentsborn1 = 0 if bornfather == 0 & bornmother == 1 | bornfather == 1 & bornmother == 0
tab parentsborn1
lab var parentsborn1 "both parents born in country"
lab var borncntry "individual born in country"
gen minority = 1 if borncntry==0 | parentsborn1==0 | ctzcntr > 1 | blgetmg==1
replace minority = 0 if borncntry==1 & parentsborn1==1 & ctzcntr==1 & blgetmg==2

*UNEMPLOYED
generate unempl=0
replace unempl= 1 if uempla==1
replace unempl= 1 if uempli==1 
recode uempnyr 1=1 2=1 3=0 4=0 .=., gen(lklunmp)
replace unempl= 1 if lklunmp==1 

*LEFT-RIGHT SCALE
*include left-right scale, but variable does not need any recoding (lrscale)

*********************************************************************************************************************************************
* OESCH CLASS SCHEMA
* Create 5-Class schema
* use Simon Kaiser (University of Bern)'s module "oesch" that creates Oesch class schema (use the commands "ssc install oesch" and "help oesch")
*Simon Kaiser, 2018. "OESCH: Stata module to recode ISCO codes into Oesch class scheme," Statistical Software Components S458490, Boston College Department of Economics, revised 23 Oct 2018. 
*************************************************************************************************************************************
**** References:
**** Oesch, D. (2006a) "Coming to grips with a changing class structure" International Sociology 21 (2): 263-288.
**** Oesch, D. (2006b) "Redrawing the Class Map. Stratification and Institutions in Britain, Germany, Sweden and Switzerland", Basingstoke: Palgrave Macmillan.
**** A few minor changes were made with respect to the procedure described in these two sources (decisions taken by Oesch and Tawfik in 2014)

**** 5-Class schema constructed
  *1 Higher-grade service class
  *2 Lower-grade service class
  *3 Small business owners
  *4 Skilled workers
  *5 Unskilled workers

**** Variables used to construct Oesch class schema: iscoco, isco08, emplrel, emplno


iskooesch class5f, isko(iscoco) emplrel(emplrel) emplno(emplno) five

iskooesch class5f2, isko(isco08) emplrel(emplrel) emplno(emplno) five

gen class5=.
replace class5 = oesch5_class5f if oesch5_class5f2 == .
replace class5 = oesch5_class5f2 if oesch5_class5f == .
label variable class5 "Final Oesch class position - 5 classes"
label define class5 ///
1 "Higher-grade service class" ///
2 "Lower-grade service class" ///
3 "Small business owners" ///
4 "Skilled workers" ///
5 "Unskilled workers"
label value class5 class5
tab class5


*****CREATING COHORT LEVEL VARIABLES*********
********REMEMBER TO CHECK THE RIGHT COUNTRY NUMBERS CORRESPONDENCE WITH THOSE IN THE IMPORTED DATASETS
generate country_num=country
*****PARTY VALUES
egen party_id=concat(country_num yrbrn)
merge m:m party_id using "data/cprinciples.dta"
drop _merge

*EQUALITY
destring equality, ignore(decimal) generate(new_equality)
drop equality
rename new_equality equality
sort yrbrn
line equality yrbrn, by(country) 
bysort cohort country: egen meanequalityc = mean(equality)
sort cohort
line meanequalityc cohort, by(country) 

*TRADITIONALISM
destring traditionalism, ignore(decimal) generate(new_traditionalism)
drop traditionalism
rename new_traditionalism traditionalism
sort yrbrn
line traditionalism yrbrn, by(country)  
bysort cohort country: egen meantraditionalismc = mean(traditionalism)
sort cohort
line meantraditionalismc cohort, xscale(range(3(1)16)) by(country)

*******Figure 1
sort year
line equality traditionalism year, by(country) 
*********


*UNIVERSITY EDUCATION PERCENTAGES
tablecol cohort uni, by (country) rowpct
bysort cohort country: egen eduunic = mean(100 * (uni==1))
sort cohort
line eduunic cohort, xscale(range(3(1)16)) by(country)


*NET MIGRATION
*Note: net migration is already at the country and cohort level
egen netmigrate_id = concat(cntry cohort)
merge m:m netmigrate_id using "data/netmigrate.dta"
drop _merge
sort cohort
line netmigrate cohort, xscale(range(3(1)16)) by(country)


*HISTORICAL UNEMPLOYMENT
egen histunemp_id=concat(country_num yrbrn)
merge m:m histunemp_id using "data/histunemployed.dta"
drop _merge
bysort cohort country: egen meanhistunemplc = mean(histunempl)

*NOTE: THE OLDEST COHORT IN EACH COUNTRY ARE ASSIGNED THE VALUE FOR THE YEAR 1956 (THE EARLIEST AVAILABLE YEAR) 
replace meanhistunemplc = 2.893983 if country==2 & cohort==3
replace meanhistunemplc = 2.168675 if country==6 & cohort==3
replace meanhistunemplc = 3.44451 if country==4 & cohort==3
replace meanhistunemplc = 5.343512 if country==10 & cohort==3
replace meanhistunemplc = 0.5896806 if country==13 & cohort==3
replace meanhistunemplc = 0.9915014 if country==14 & cohort==3
replace meanhistunemplc = 1.740644 if country==15 & cohort==3
replace meanhistunemplc = 0.1164325 if country==3 & cohort==3
replace meanhistunemplc = 0.9202191 if country==8 & cohort==3
replace meanhistunemplc = 3.560371 if country==1 & cohort==3
replace meanhistunemplc = 5.563986 if country==5 & cohort==3
replace meanhistunemplc = 1.143678 if country==7 & cohort==3
replace meanhistunemplc = 1.440922 if country==11 & cohort==3
replace meanhistunemplc = 9.90991 if country==12 & cohort==3


sort yrbrn
line histunempl yrbrn, by(country)
sort cohort
line meanhistunemplc cohort, xscale(range(3(1)16)) by(country)

*****CREATING PERIOD LEVEL VARIABLES
*UNIVERSITY
tablecol essround uni, by (country) rowpct
bysort essround country: egen eduunip = mean(100 * (uni==1))
sort essround
line eduunip essround, xscale(range(1(1)10)) by(country)

*NET MIGRATION INDEX
egen pernetmig_id=concat(country_num essround)
merge m:m pernetmig_id using "data/pernetmigrate.dta"
drop _merge
sort essround
line pernetmig essround, xscale(range(1(1)10)) by(country)

*PERIOD UNEMPLOYMENT
egen perunempl_id=concat(country_num essround)
merge m:m perunempl_id using "data/perunempl.dta"
drop _merge
sort essround
line perunemp essround, xscale(range(1(1)10)) by(country)


*PARTY VALUES
egen perparty_id=concat(country_num essround)
merge m:m perparty_id using "data/pprinciples.dta"
drop _merge

*EQUALITY
destring pequality, ignore(decimal) generate(new_pequality)
drop pequality
rename new_pequality pequality
sort essround
line pequality essround, xscale(range(1(1)10)) by(country)

*TRADITIONALISM
destring ptraditionalism, ignore(decimal) generate(new_ptraditionalism)
drop ptraditionalism
rename new_ptraditionalism ptraditionalism
sort essround
line ptraditionalism essround, xscale(range(1(1)10)) by(country)


***********ANALYSIS
*generating missing variable count to use only cases with valid observations across all variables
*capture drop missing
egen missing=rmiss(allage lsec usec subdeg uni female urban incdiff minority unempl lrscale class5 ///
meanequalityc meantraditionalismc eduunic meanhistunemplc netmigrate   ///
eduunip pernetmig perunemp pequality ptraditionalism ///
)
drop if missing>0

*we start with a null model
*MODEL 0
egen new=concat(cohort essround)
egen cntcoh=concat(country cohort)
egen cntess=concat(country essround)


mixed imgall || country: || _all:R.cntcoh || cntess: , variance
estimate store M0

outreg2 using cohort_m0.doc, sideway /// 
replace ctitle(Coef) ///
alpha(0.001, 0.01, 0.05) symbol(***, **, *) 


********PREDICTING COUNTRY, PERIOD AND COHORT RANDOM EFFECTS******
egen pickone_country = tag(country)
egen pickone_cohort = tag(cohort)
egen pickone_p = tag(essround)


*COUNTRY
predict z0, reffects relevel(country)
predict z0se, reses relevel(country)

*we rank countries by the magnitude of their predicted effects
egen z0rank = rank(z0) if pickone_country==1
sort z0rank 
list country z0 z0se z0rank if pickone_country==1, noobs
generate labheightc = z0 + 1.96*z0se + 0.05

***********************FIGURE 2
serrbar z0 z0se z0rank if pickone_country==1, scale(1.96) yline(0) ///
addplot(scatter labheightc z0rank, ///
msymbol(none) mlabel(country) ///
mlabposition(1) mlabangle(vertical) mlabcolor(navy)) ///
ytitle("Predicted country effect") xtitle("Rank") ///
legend(off)
*****************************
	
*COHORT RANDOM EFFECTS FOR EACH COUNTRY SEPARATELY
egen group = group(country)
gen c02 = .
gen c0se2 = .
gen pr_c_low2 = .
gen pr_c_high2 = .
su group, meanonly

forval g = 1/`r(max)' {
    quietly mixed imgall if group == `g' || _all: R.cohort || essround:, variance
    predict re, reffects relevel(_all)
	predict se, reses relevel(_all)
    replace c02 = re if group == `g' 
	replace c0se2 = se if group == `g' 
    drop re
	drop se
	replace pr_c_low2 = (c02 - c0se2) if group == `g' 
    replace pr_c_high2 = (c02 + c0se2) if group == `g' 
}

************FIGURE 3	
twoway (rarea pr_c_low2 pr_c_high2 cohort, sort fcolor(gs13) lcolor(white)) ///
	(line c02 cohort, sort mcolor(black) msymbol(circle) lcolor(black) ///
	lwidth(medthick)) ///
	, ytitle("") yline(0) ///
	xtitle("") xlabel(3(1)16, labsize(large)) ///
	legend(off) graphregion(fcolor(white) lcolor(white)) ///
	by(country, title("Cohort Random Effects by Country", size(medsmall)))
****************************************	


*PERIODS FOR COUNTRIES SEPARATELY
gen p02 = .
gen p0se2 = .
gen pr_p_low2 = .
gen pr_p_high2 = .
su group, meanonly

forval g = 1/`r(max)' {
    quietly mixed imgall if group == `g' || _all: R.cohort || essround:, variance
    predict re, reffects relevel(essround)
	predict se, reses relevel(essround)
    replace p02 = re if group == `g' 
	replace p0se2 = se if group == `g' 
    drop re
	drop se
	replace pr_p_low2 = (p02 - p0se2) if group == `g' 
    replace pr_p_high2 = (p02 + p0se2) if group == `g' 
}

*****************FIGURE 4
twoway (rarea pr_p_low2 pr_p_high2 essround, sort fcolor(gs13) lcolor(white)) ///
	(line p02 essround, sort mcolor(black) msymbol(circle) lcolor(black) ///
	lwidth(medthick)) ///
	, ytitle("") yline(0) ///
	xtitle("") xlabel(1(1)10, labsize(large)) ///
	legend(off) graphregion(fcolor(white) lcolor(white)) ///
	by(country, title("Period Random Effects by Country", size(medsmall)))
************************************

	

*MODEL 1 (ONLY INDIVIDUAL LEVEL)
mixed imgall allage i.lsec i.usec i.subdeg i.uni i.female i.urban i.incdiff i.minority i.unempl lrscale i.class5 ///
|| country: || _all:R.cohort || essround: , variance

outreg2 using cohort_m1.doc, sideway /// 
replace ctitle(Coef) ///
alpha(0.001, 0.01, 0.05) symbol(***, **, *) 


*MODEL 2 (COHORT AND PERIOD LEVEL PARTY EQUALITY)
mixed imgall allage i.lsec i.usec i.subdeg i.uni i.female i.urban i.incdiff i.minority i.unempl lrscale i.class5 ///
meanequalityc ///
pequality ptraditionalism pernetmig perunemp eduunip ///
|| country: || _all:R.cohort || essround: , variance iterate(20)

outreg2 using cohort_m2.doc, sideway /// 
replace ctitle(Coef) ///
alpha(0.001, 0.01, 0.05, 0.1) symbol(***, **, *, +)


*MODEL 3 (COHORT AND PERIOD LEVEL PARTY TRADITIONALISM)
mixed imgall allage i.lsec i.usec i.subdeg i.uni i.female i.urban i.incdiff i.minority i.unempl lrscale i.class5 ///
meantraditionalismc ///
pequality ptraditionalism pernetmig perunemp eduunip ///
|| country: || _all:R.cohort || essround: , variance iterate(20)

outreg2 using cohort_m3.doc, sideway /// 
replace ctitle(Coef) ///
alpha(0.001, 0.01, 0.05, 0.1) symbol(***, **, *, +)


*MODEL 4 (ALL COHORT AND PERIOD LEVEL)
mixed imgall allage i.lsec i.usec i.subdeg i.uni i.female i.urban i.incdiff i.minority i.unempl lrscale i.class5 ///
meanequalityc meantraditionalismc eduunic netmigrate meanhistunemplc  ///
pequality ptraditionalism pernetmig perunemp eduunip ///
|| country: || _all:R.cohort || essround: , variance

outreg2 using cohort_m4.doc, sideway /// 
replace ctitle(Coef) ///
alpha(0.001, 0.01, 0.05, 0.1) symbol(***, **, *, +)

